package com.virtualparadigm.compositor;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;

import com.virtualparadigm.identity.Identifiable;
import com.virtualparadigm.identity.ResourceIdentifier;

public class OneToOneCompositorDelegate<CompositorType extends Identifiable> extends CompositorDelegate<CompositorType>
{
	private static final long serialVersionUID = 1L;
	
	private OneToOneCompositePart<CompositorType> oneToOneCompositePart;
	
	public OneToOneCompositorDelegate(CompositorType instance)
	{
		super(instance);
	}
	
	public <CompositePartType> CompositePartType getCompositePart()
	{
		CompositePartType typedCompositePart = null;
		if(this.oneToOneCompositePart != null)
		{
			// remember that all composite parts are implemented via "inheritance" NOT "composition", so simply casting it is legitimate
			typedCompositePart = (CompositePartType)this.oneToOneCompositePart;
		}
		return typedCompositePart;
	}
	
	public void setCompositePart(OneToOneCompositePart<CompositorType> oneToOneCompositePart)
	{
		if(this.oneToOneCompositePart == null)
		{
			if(oneToOneCompositePart != null)
			{
				this.oneToOneCompositePart = oneToOneCompositePart;
				oneToOneCompositePart.setOneToOneCompositorDelegate(this);
			}
		}
		else
		{
			if(!this.oneToOneCompositePart.equals(oneToOneCompositePart))
			{
				OneToOneCompositePart<CompositorType> tempCompositePart = this.oneToOneCompositePart;
				this.oneToOneCompositePart = oneToOneCompositePart;
				tempCompositePart.setOneToOneCompositorDelegate(null);
				
				if(oneToOneCompositePart != null)
				{
					oneToOneCompositePart.setOneToOneCompositorDelegate(this);
				}
			}
		}
	}
	
	
	
//	// package protected
//	OneToOneCompositePart<CompositorType> getOneToOneCompositePart()
//	{
//		return this.oneToOneCompositePart;
//	}
//	
//	// package protected
//	void setOneToOneCompositePart(OneToOneCompositePart<CompositorType> oneToOneCompositePart)
//	{
//		if(this.oneToOneCompositePart == null)
//		{
//			if(oneToOneCompositePart != null)
//			{
//				this.oneToOneCompositePart = oneToOneCompositePart;
//				oneToOneCompositePart.setOneToOneCompositor(this);
//			}
//		}
//		else
//		{
//			if(!this.oneToOneCompositePart.equals(oneToOneCompositePart))
//			{
//				OneToOneCompositePart<CompositorType> tempCompositePart = this.oneToOneCompositePart;
//				this.oneToOneCompositePart = oneToOneCompositePart;
//				tempCompositePart.setOneToOneCompositor(null);
//				
//				if(oneToOneCompositePart != null)
//				{
//					oneToOneCompositePart.setOneToOneCompositor(this);
//				}
//			}
//		}
//	}
//	

	
	
	
	@Override
	public boolean removeCompositePart(ResourceIdentifier resourceIdentifier)
	{
		boolean status = false;
		if(this.oneToOneCompositePart != null && this.oneToOneCompositePart.getResourceIdentifier().equals(resourceIdentifier))
		{
			this.setCompositePart(null);
			status = true;
		}
		return status;
	}

	@Override
	public boolean putCompositePart(CompositePart<CompositorType> compositePart)
	{
		this.setCompositePart((OneToOneCompositePart<CompositorType>)compositePart);
		return true;
	}
	
	// ================================================
	// UTILITY METHODS
	// ================================================
	public String toString()
	{
//		return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
		return ReflectionToStringBuilder.toString(this, ToStringStyleBuilder.toStringStyle);
	}
	public int hashCode()
	{
		HashCodeBuilder builder = new HashCodeBuilder();
	    builder.append(this.getCompositor().getResourceIdentifier());
	    return builder.toHashCode();		
	}
	public boolean equals(Object obj)
	{
		if (obj == null)
		{
			return false;
		}
		if (obj == this)
		{
			return true;
		}
		if (obj.getClass() != getClass())
		{
			return false;
		}
		OneToOneCompositorDelegate<CompositorType> that = (OneToOneCompositorDelegate<CompositorType>)obj;
		EqualsBuilder builder = new EqualsBuilder();
	    builder.append(this.getCompositor().getResourceIdentifier(), that.getCompositor().getResourceIdentifier());
		return builder.isEquals();
	}

	
	
	
	
}